<?php

include_once('dao_log.php');
include_once('dao_conv.php');
include_once('dao_common.php');
include_once('../../config/dao.cfg.php');
define( 'DB_CONNECT_FAILED', 'CONNECT' );
define( 'DB_QUERY_FAILED', 'SQL' );
define( 'DB_CLOSE_FAILED', 'CLOSE' );
static $db_pool =array();



/*
中文的常见SQL错误，e文的可以直接取mysql_error
可能不完整，发现后再添加
*/
global $mysql_error_cn;
$mysql_error_cn[0]='成功';
$mysql_error_cn[1005]='创建表失败';
$mysql_error_cn[1006]='创建数据库失败';
$mysql_error_cn[1007]='数据库已存在，创建数据库失败';
$mysql_error_cn[1008]='数据库不存在，删除数据库失败';
$mysql_error_cn[1009]='不能删除数据库文件导致删除数据库失败';
$mysql_error_cn[1010]='不能删除数据目录导致删除数据库失败';
$mysql_error_cn[1011]='删除数据库文件失败';
$mysql_error_cn[1012]='不能读取系统表中的记录';
$mysql_error_cn[1020]='记录已被其他用户修改';
$mysql_error_cn[1021]='硬盘剩余空间不足，请加大硬盘可用空间';
$mysql_error_cn[1022]='关键字重复，更改记录失败';
$mysql_error_cn[1023]='关闭时发生错误';
$mysql_error_cn[1024]='读文件错误';
$mysql_error_cn[1025]='更改名字时发生错误';
$mysql_error_cn[1026]='写文件错误';
$mysql_error_cn[1032]='记录不存在';
$mysql_error_cn[1036]='数据表是只读的，不能对它进行修改';
$mysql_error_cn[1037]='系统内存不足，请重启数据库或重启服务器';
$mysql_error_cn[1038]='用于排序的内存不足，请增大排序缓冲区';
$mysql_error_cn[1040]='已到达数据库的最大连接数，请加大数据库可用连接数';
$mysql_error_cn[1041]='系统内存不足';
$mysql_error_cn[1042]='无效的主机名';
$mysql_error_cn[1043]='无效连接';
$mysql_error_cn[1044]='当前用户没有访问数据库的权限';
$mysql_error_cn[1045]='不能连接数据库，用户名或密码错误';
$mysql_error_cn[1046]='未指定数据库';
$mysql_error_cn[1048]='字段不能为空';
$mysql_error_cn[1049]='数据库不存在';
$mysql_error_cn[1050]='数据表已存在';
$mysql_error_cn[1051]='数据表不存在';
$mysql_error_cn[1054]='字段不存在';
$mysql_error_cn[1062]='记录重复,增加或修改失败';
$mysql_error_cn[1064]='SQL语句语法错误';
$mysql_error_cn[1065]='无效的SQL语句，SQL语句为空';
$mysql_error_cn[1081]='不能建立Socket连接';
$mysql_error_cn[1114]='数据表已满，不能容纳任何记录';
$mysql_error_cn[1116]='打开的数据表太多';
$mysql_error_cn[1129]='数据库出现异常，请重启数据库';
$mysql_error_cn[1130]='连接数据库失败，没有连接数据库的权限';
$mysql_error_cn[1133]='数据库用户不存在';
$mysql_error_cn[1141]='当前用户无权访问数据库';
$mysql_error_cn[1142]='当前用户无权访问数据表';
$mysql_error_cn[1143]='当前用户无权访问数据表中的字段';
$mysql_error_cn[1146]='数据表不存在';
$mysql_error_cn[1147]='未定义用户对数据表的访问权限';
$mysql_error_cn[1149]='SQL语句语法错误';
$mysql_error_cn[1158]='网络错误，出现读错误，请检查网络连接状况';
$mysql_error_cn[1159]='网络错误，读超时，请检查网络连接状况';
$mysql_error_cn[1160]='网络错误，出现写错误，请检查网络连接状况';
$mysql_error_cn[1161]='网络错误，写超时，请检查网络连接状况';
$mysql_error_cn[1169]='字段值重复，更新记录失败';
$mysql_error_cn[1177]='打开数据表失败';
$mysql_error_cn[1180]='提交事务失败';
$mysql_error_cn[1181]='回滚事务失败';
$mysql_error_cn[1203]='当前用户和数据库建立的连接已到达数据库的最大连接数，请增大可用的数据库连接数或重启数据库';
$mysql_error_cn[1205]='加锁超时';
$mysql_error_cn[1211]='当前用户没有创建用户的权限';
$mysql_error_cn[1216]='外键约束检查失败，更新子表记录失败';
$mysql_error_cn[1217]='外键约束检查失败，删除或修改主表记录失败';
$mysql_error_cn[1226]='当前用户使用的资源已超过所允许的资源，请重启数据库或重启服务器';
$mysql_error_cn[1227]='权限不足，您无权进行此操作';
$mysql_error_cn[1235]='MySQL版本过低，不具有本功能';
$mysql_error_cn[2002]="Can't connect to ..没有一个MySQL服务器运行在系统上或网络错误";


class DAO_Mysql
{
	public $host;
	public $user;
	public $password;
	public $dbname;
	public $b_keep_connect;
	public $dbhandle=NULL;

	function __construct()
	{

	}
	
	function __destruct()
	{
		$this->close();
	}
	
	public function  keep_connect($v)
	{
		$this->b_keep_connect = $v;
	}
	
	public function mysql_error($lang='cn')
	{
		global $mysql_error_cn;
		$code = mysql_errno($this->dbhandle);
		if(array_key_exists($code,$mysql_error_cn))
		{
			$msg_cn =  "($code)".$mysql_error_cn[$code];
		}
		$msg_en = "($code)".mysql_error($this->dbhandle);
		if($lang=='cn')return $msg_cn;
		if($lang=='en')return $msg_en;
		return "$msg_cn;$msg_en";
	}
	
	//----------------------------------
	//连接mysql,是否使用长连接取决于$b_keep_connect;
	public function open(&$msg='')
	{
		DAO_Log::debug('connect mysql(keep:'.$this->b_keep_connect.'):-h'.$this->host.' -u'.$this->user.',pass:'.$this->password);
		if(!$this->b_keep_connect)
		{
			$this->dbhandle = mysql_connect( $this->host, $this->user,$this->password );
		}
		else
		{
			$this->dbhandle = mysql_pconnect( $this->host, $this->user,$this->password );
		}
		if(!$this->dbhandle)
		{
			$msg=DB_CONNECT_FAILED.':'.$this->mysql_error() ;
			return mysql_errno();
		}
		if($this->dbname)
		{
			$result =$this->usedb($this->dbname,$msg);
			if($result)
			{
				DAO_Log::debug('connect mysql:'.$this->host.' -u'.$this->user.' success but usedb error '.$msg);
			}
		}
		return 0;
	}
	
	//关闭mysql,如果是长连接，则 do nothing
	public  function  close()
	{
		global $db_pool;
		if(!$this->b_keep_connect)
		{
			if($this->is_open())
			{
				DAO_Log::debug("disconnect mysql($this->dbname):".$this->host.' -u'.$this->user);
				mysql_close($this->dbhandle);
			}
			unset($this->dbhandle);
			$this->dbhandle=NULL;
		}
		else
		{
			DAO_Log::debug('leave mysql keep connection:'.$this->host.' -u'.$this->user);
		}
	}
	
	public function is_open()
	{
		if(!isset($this->dbhandle)|| !is_resource($this->dbhandle))
		{
			return false;
		}
		else
		{
			return true;
		}
	}
	
	public function usedb($dbname_,&$msg=NULL)
	{

		$sql='use '.$dbname_;
		$result = mysql_select_db($dbname_,$this->dbhandle);
		if($result)
		{
			//成功
			$this->dbname=$dbname_;
			$result = 0;
		}
		else
		{
			//失败
			$msg  = $this->mysql_error();
			$result = mysql_errno();
		}
		return $result;
	}
	
	//批量执行SQL ,$sqlbatch是包含多个sql语句的数组
	public function exec_sql_batch(&$sqlbatch,&$table=NULL,&$field=NULL,&$msg='')
	{
		$ret = 0;
		if(strlen($sqlbatch[0])==0)
		{
			$msg = 'no statement';
			return -1;
		}
		foreach ($sqlbatch as $key=>$value)
		{
			$ret = $this->exec_sql($value,$table,$field,true,$msg);
			if($ret)
			{
				$msg = "error in batch[$key]:".$msg;
				return $ret;
			}
		}
		return $ret;
	}


	//fetch 并回调
	public function fetch_callback($sql,$callback,$msg)
	{
		$ret = $this->exec_sql($sql,$recordset,$affect,false,$msg);
		if($ret)
		{
			return $ret;
		}
		if(!function_exists($callback))
		{
			return 0;
		}
		while(true)
		{
			$ret = $this->fetch($recordset,$row,$msg);
			if($ret==0)
			{
				$callback($row);
			}
			if($ret)break;
		}
	}
	
	public function fetch(&$result,&$row,&$msg)
	{
		$row = mysql_fetch_assoc( $result );
		if($row===false)
		{
			$msg = $this->mysql_error();
			$ret =  mysql_errno();
			if($ret==0)
			{
				$ret =  1;//结束
			}
			mysql_free_result($result);
			return $ret;
		}
		return 0;
	}

	//notice此方法不负责初始化$table,而是将记录递增到table的尾部。初始化由调用者负责，
	//返回：0表示成功，非0表示失败，>0表示mysql的错误码
	public  function exec_sql($sql,&$table=NULL,&$affect_rows=NULL,$b_fetch_data,&$msg='')
	{
		if(!isset($this->dbhandle))
		{
			$result = $this->open($msg);
			if($result)
			return $result;
		}
		DAO_Log::debug("exec sql:\r\n        ".$sql."<<");
		$result=false;
		if(!$this->dbhandle)
		{
			$msg = DB_QUERY_FAILED.'DB NOT OPEN:'.$this->host.';'.$this->mysql_error();
			return mysql_errno();
		}
		$result = mysql_query($sql,$this->dbhandle);
		if(!$result)
		{
			$msg = DB_QUERY_FAILED.';'.$this->mysql_error();
			return mysql_errno();
		}
		$affect_rows = mysql_affected_rows ($this->dbhandle);
		DAO_Log::debug("query affect rows:$affect_rows.result: $result");
		if(!is_resource($result))
		{
			//==TRUE/FALSE,是inert/update/delete操作
			if($affect_rows==0)
			{
				$msg = 'execute sql success but 0 rows affected';
			}
			return 0;
		}
		//$table=array();初始化table不是此函数的职责，由调用者负责
		if($b_fetch_data)
		{
			while( $row = mysql_fetch_assoc( $result ))
			{
				$table[]=$row;
			}
			mysql_free_result($result);
		}
		else
		{
			$table = $result;//将结果返回给调用者fetch
		}
		return 0;
	}
}

//-----------------------------------------
//获取全局连接

//------------------------------------------
//连接配置列表，列表包含连接信息元素
//每个连接信息包括键: host ,user, pass
//相同的配置将导致相同的连接。
$db_pool=array();
//return NULL for failure
function &get_sql_connection($conn_name='',&$msg=NULL,$auto_open = true)
{
	global $db_pool;	
	global $db_connection_config;
	if(strlen($conn_name)==0)
	{
		DAO_Log::error('unknwo connect name');
		return NULL;
	}
		if(!array_key_exists($conn_name,$db_connection_config[ENV]) )
		{
			 $msg = "dbconfig:error:$conn_name is not configure";
			 DAO_Log::error("$msg");
			 return NULL;
		}
	//根据host,user,拼接成连接对象的key.因为相同host,user将导致相同的连接
	$conn_config = $db_connection_config[ENV][$conn_name];
	$conn_pool_key = $conn_config['host'].$conn_config['user'];
	if(strlen($conn_pool_key)==0)
	{
		$conn_pool_key='local_default';
	}
	if(!array_key_exists($conn_pool_key,$db_pool))
	{
	
		
		$db_pool[$conn_pool_key]=new DAO_Mysql();
		$db_pool[$conn_pool_key]->user=$conn_config['user'];
		$db_pool[$conn_pool_key]->password=$conn_config['pwd'];
		$db_pool[$conn_pool_key]->host = $conn_config['host'];
		$db_pool[$conn_pool_key]->dbname='';
		$db_pool[$conn_pool_key]->keep_connect($conn_config['keepconnect']);
		
	}
	
	if(!$db_pool[$conn_pool_key]->is_open()&&$auto_open)
	{
		DAO_Log::debug("db authOpen to $conn_name");
		$ret = $db_pool[$conn_pool_key]->open($msg);
		if($ret!=0)
		{
			DAO_Log::error("open  dbPool $conn_name error : $msg,".$conn_config["host"].",".$conn_config["user"].",".$conn_config["pass"]);
			return NULL;
		}
		$db_pool[$conn_pool_key]->exec_sql('SET NAMES GBK');
	}
	return $db_pool[$conn_pool_key];
}

?>